﻿using System.Collections.Generic;
using System.Linq;
using BlogsAPI.Sites;
using RssToolkit.Rss;

namespace BlogsAPI.BlogsYandex
{
    using System;
    using System.IO;
    using System.Web;
    using System.Net;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Diagnostics;
    using Abstract;

    /// <summary>
    /// Класс для обработки информации об одном посте, такой как ссылки, комменты и т.д.
    /// </summary>
    [Obsolete("Весьма устаревший функционал")]
    public class PostWatch : WebInterface
    {
        #region Свойства

        /// <summary>
        /// На выходе 
        /// 1 - ссылка на пост
        /// 2 - заголовок поста
        /// 3 - ссылка на текст поста
        /// 4 - цифры,
        /// 5 - типы из трех букв...
        /// </summary>
        private readonly Regex _rParser = new Regex(@"<h3\s+class\W+title[^<]+<a\s+href\W+([^'""]+)[^>]+>([^<]+).*?<a class\W+link[^>]+href\W+((?:http:)?//blogs\.yandex\.ru/cachedcopy\.xml[^'""]+)"
            + @"(?:.*?(?:</table>|(?:rd=0|comments)\W+class\W+link\W\D+([\d\s]+)\s(\w{3}))){0,2}",
            RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline);

        /// <summary>
        /// 1 - содержимое поста
        /// </summary>
        private readonly Regex _rGetPost = new Regex(@"<div class\W+nonyandexcontent[^<]+(.*)</div[^<]+<div class\W+cachedcopynote",
            RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline);

        /// <summary>
        /// Извлечение авторитетности и прочего счастья.
        /// 1 - номер позиции в рейтинге
        /// 2 - авторитетность
        /// 3 - читателей
        /// </summary>
        private readonly Regex _rCountReaders = new Regex(@"<tr class\W+found[^<]+<td class\W+first\D+(\d+).*?<td>\D+(\d+)\D+(\d+)\D+?</td[^<]+</tr>",
            Regexoptions);

        /// <summary>
        /// Извлечение аватарки блогера
        /// </summary>
        private Regex _rAvatar = new Regex(@"background\-image:url\(([^\)]+)\)",
            Regexoptions);

        /// <summary>
        /// Удаление неформатных пробелов =(
        /// </summary>
        private readonly Regex _rSpace = new Regex(@"\D",
            Regexoptions);

        /// <summary>
        /// На выходе 
        /// 1 - ссылка на ТОП
        /// 2 - миниаватарка в виде <img />
        /// 3 - Название
        /// 4 - Количество отзывов
        /// </summary>
        /*private Regex _rTop30 = new Regex(@"<dt class\W+name.*?href\W+([^'""]+)[^>]+>(?:<.*?>(<img.*?>)</i>)?([^<]+)<.*?class\W+b-bubble-comm\D+(\d+)\s",
            RegexOptions.Compiled | RegexOptions.IgnoreCase);*/

        #endregion

        #region Функции формирования правильных ссылок

        /// <summary>
        /// Проверка, находится ли ссылка в кэше.
        /// </summary>
        /// <param name="linkto"></param>
        /// <returns></returns>
        public Boolean IsCachedLink(string linkto)
        {
            return linkto.Contains("/cachedcopy.xml?");
        }

        /// <summary>
        /// Формируем ссылку для поиска в яндексе числа отзывов и комментов
        /// </summary>
        /// <param name="rss">выдача в RSS или XML</param>
        /// <param name="page">номер страницы, начинается с 0</param>
        /// <returns>Ссылка для поиска в Яндексе</returns>
        public static String FormYandexSearch2(string searchphrase, Boolean rss = false, 
            DateTime? date_start = null, DateTime? date_end = null,
            int page = 0, string where = "blog")
        {
            string date_string = String.Empty;
            if (date_start != null)
            {
                //&from_day=10&from_month=11&from_year=2012
                date_string += String.Format("&from_day={0}&from_month={1}&from_year={2}",
                    date_start.Value.Day,
                    date_start.Value.Month,
                    date_start.Value.Year);
            }
            if (date_end != null)
            {
                date_string += String.Format("&to_day={0}&to_month={1}&to_year={2}",
                    date_end.Value.Day,
                    date_end.Value.Month,
                    date_end.Value.Year);
            }
            return String.Format("https://blogs.yandex.ru/search.{0}?text={1}&p={2}&ft={3}{4}",
                rss ? "rss" : "xml", 
                HttpUtility.UrlEncode(searchphrase),
                page, where,
                (date_start==null && date_end==null?"":"&date=on"+date_string)
                );

        }

        /// <summary>
        /// Формируем ссылку для поиска в яндексе числа отзывов и комментов
        /// </summary>
        /// <param name="bloglink">Ссылка на блог корень</param>
        /// <param name="rss">выдача в RSS или XML</param>
        /// <param name="page">номер страницы, начинается с 0</param>
        /// <returns>Ссылка для поиска в Яндексе</returns>
        public static String FormYandexSearch(String bloglink, Boolean rss = false, int page = 0, string where = "blog")
        {
            return String.Format("https://blogs.yandex.ru/search.{1}?author={0}&p={2}&ft={3}",
                HttpUtility.UrlEncode(bloglink), rss ? "rss" : "xml", page, where);

        }

        /// <summary>
        /// формируем ссылку на RSS всех комментариев к записям
        /// </summary>
        /// <param name="bloglink"></param>
        /// <returns></returns>
        public static String FormYandexComments(String bloglink, Boolean rss = false, int page = 0)
        {
            return String.Format("https://blogs.yandex.ru/search.{1}?ft=comments&full=1&p={2}&post={0}",
                HttpUtility.UrlEncode(bloglink), rss ? "rss" : "xml", page);
        }

        /// <summary>
        /// формируем ссылку на RSS всех ссылок на запись
        /// </summary>
        /// <param name="bloglink">ссылка на пост</param>
        /// <param name="rss">RSS or XML</param>
        /// <param name="page">page number</param>
        /// <param name="where">опция типа поиска</param>
        /// <returns></returns>
        public static String FormYandexLinks(String bloglink, Boolean rss = false, int page = 0, string where = "blog")
        {
            //используем XML а не RSS, так как у Яндекса все криво...
            return String.Format("https://blogs.yandex.ru/search.{1}?link={0}&full=1&p={2}&ft={3}",
                HttpUtility.UrlEncode(bloglink), rss ? "rss" : "xml", page, where);
        }

        /// <summary>
        /// формируем ссылку на получение информации о блоге, типа числа читателей и авторитетность и т.п.
        /// </summary>
        //private static String FormYandexReaders(String blogname, BlogType bt)
        //{
        //    return String.Format("https://blogs.yandex.ru/top/" + (bt == BlogType.Community ? "com/" : "") + "?username={0}",
        //        HttpUtility.UrlEncode(blogname));
        //}

        #endregion

        /// <summary>
        /// Извлечение ссылок и числа комментов к посту из яндекса
        /// </summary>
        /// <param name="bp">ссылка на пост!</param>
        /// <param name="bp.iL">значение отзывов</param>
        /// <param name="bp.iC">значение комментов</param>
        /// <param name="bp.Subject">Заголовок поста</param>
        /// <param name="bp.Body">Ссылка на полное описание поста</param>
        /// <returns></returns>
        //public bool ExtractLinksComms(BlogPost bp)
        //{
        //    try
        //    {
        //        string username;
        //        BlogType bt;
        //        //нужно обрезать ссылку, чтобы получить автора
        //        object blogService = Common.GetBlogServiceByLink(bp.Link.OriginalString,
        //            out username, out bt);
        //        if (blogService != null)//найден таки
        //        {
        //            string bloglink = ((BlogServer)blogService).GetBlogLink(username, bt);
        //            bloglink = bloglink.ToLower();

        //            HttpWebRequest myHttpWebRequest = MakeRequest(FormYandexSearch(bloglink));
        //            myHttpWebRequest.Method = "GET"; // метод GET
        //            myHttpWebRequest.Referer = "https://blogs.yandex.ru";
        //            //получаем ответ и его разбираем...
        //            var myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
        //            string result = new StreamReader(myHttpWebResponse.GetResponseStream(), Encoding.UTF8).ReadToEnd();
        //            myHttpWebResponse.Close();
        //            //есть ответ, надо его пропарсить..
        //            //если найдено что-то, то нолик проставим
        //            bp.Comments = bp.Links = 0;
        //            //проверим, если там вообще то, что надо..
        //            if (result.Contains(bp.Link.OriginalString))
        //            {
        //                //заменяем фишки яндекса...вот уроды...
        //                result = result.Replace("<wbr/>", "");
        //                //устроим-ка разбор
        //                MatchCollection mc = _rParser.Matches(result);
        //                if (mc.Count > 0)//что-то выцепили
        //                {
        //                    foreach (Match m in mc)
        //                    {
        //                        //данные не относятся к искомому посту
        //                        if (String.Compare(bp.Link.OriginalString, m.Groups[1].ToString(), true) != 0) continue;
        //                        ///есть ненулевые данные
        //                        if (m.Groups[4].Captures.Count > 0)
        //                        {
        //                            for (int i = 0; i < m.Groups[4].Captures.Count; i++)
        //                            {
        //                                if (String.Compare(m.Groups[5].Captures[i].ToString(), "ком", true) == 0)
        //                                {
        //                                    //комменты
        //                                    bp.Comments = int.Parse(_rSpace.Replace(m.Groups[4].Captures[i].ToString(), ""));
        //                                }
        //                                else
        //                                {
        //                                    //отзывы
        //                                    bp.Links = int.Parse(_rSpace.Replace(m.Groups[4].Captures[i].ToString(), ""));
        //                                }
        //                            }
        //                        }
        //                        if (String.IsNullOrEmpty(bp.Body))
        //                        {
        //                            //кроме того отметим заголовок поста...
        //                            bp.Subject = m.Groups[2].Value;
        //                            bp.Body = "https://"+Common.DelHttp(m.Groups[3].Value.TrimStart('/')); //ccылка на текст поста, если нужно
        //                        }
        //                        break;
        //                    }
        //                }
        //            }
        //            else//если нет в Яндексе, то просто откроем пост и воьмем число комментариев
        //            {
        //                uint? loaded = Common.HowManyComments(bp.Link.OriginalString);
        //                if (loaded != null)
        //                {
        //                    bp.Comments = (int)loaded;
        //                }
        //            }
        //        }
        //        return true;
        //    }
        //    catch (Exception e1)
        //    {
        //        Debug.WriteLine("Ошибка извлечения числа ссылок и комментов из Яндекса: " + e1.Message);
        //        bp.Comments = bp.Links = -1;
        //        return false;
        //    }
        //}


        /// <summary>
        /// Извлечение ссылок и числа комментов к посту из яндекса
        /// </summary>
        /// <param name="linkon">ссылка на блог</param>
        /// <param name="page">номер страницы</param>
        /// <param name="where">тип поиска</param>
        /// <returns></returns>
        public RssDocument ExtractLinksCommsRss(String linkon, int page, string where = "blog")
        {
            try
            {
                return RssDocument.Load(new Uri(FormYandexSearch(linkon, true, page, where)));
            }
            catch (Exception e1)
            {
                Debug.WriteLine("Ошибка извлечения числа ссылок и комментов из Яндекса - rss: " + e1.Message);
                return null;
            }
        }

        /// <summary>
        /// Извлечение целиковых ссылок на запись из яндекса
        /// </summary>
        /// <param name="linkon">ссылка на блог</param>
        /// <param name="page">номер страницы</param>
        /// <param name="where">тип поиска </param>
        /// <returns></returns>
        public RssDocument ExtractLinksRss(String linkon, int page, string where = "blog")
        {
            try
            {
                return RssDocument.Load(new Uri(FormYandexLinks(linkon, true, page, where)));
            }
            catch (Exception e1)
            {
                Debug.WriteLine("Ошибка извлечения ссылок из Яндекса - rss: " + linkon + " " + e1.Message);
                return null;
            }
        }


        /// <summary>
        /// Извлечение целиковых комментов на запись из яндекса
        /// </summary>
        /// <param name="linkon">ссылка на блог</param>
        /// <param name="page">номер страницы</param>
        /// <returns></returns>
        public RssDocument ExtractCommentsRss(String linkon, int page)
        {
            try
            {
                YaRu ya = new YaRu();
                string userName;
                BlogType bt;
                if (ya.ValidateLink(linkon, out userName, out bt))
                {
                    //нужна отдельная проверка для постов с Ya.ru, так как они извлекаются по особому =((
                    //вначале нужно узнать номер дневника.
                    RssDocument rDoc = RssDocument.Load(new Uri(ya.GetRssLink(userName, bt)));
                    //далее проходимся по всем постам и ищем ссылку нашу, и берем guid
                    bool changed = false;
                    foreach (var item in rDoc.Channel.Items)
                    {
                        if (String.Compare(item.Link, linkon, StringComparison.OrdinalIgnoreCase) == 0)//совпало!
                        {
                            linkon = item.Guid.Text;
                            changed = true;
                            break;
                        }
                    }
                    if (!changed) return null;
                }
                return RssDocument.Load(new Uri(FormYandexComments(linkon, true, page)));
            }
            catch (Exception e1)
            {
                Debug.WriteLine("Ошибка извлечения комментов из Яндекса - rss: " + linkon + " " + e1.Message);
                return null;
            }
        }

        /// <summary>
        /// Ссылка на пост в кэше яндекса
        /// </summary>
        /// <param name="blink"></param>
        /// <returns></returns>
        public string GetYandexPost(string blink)
        {
            if (String.IsNullOrEmpty(blink))
            {
                return "";
            }
            HttpWebRequest myHttpWebRequest = MakeRequest(blink);
            myHttpWebRequest.Method = "GET"; // метод GET
            myHttpWebRequest.Referer = "https://blogs.yandex.ru";
            //получаем ответ и его разбираем...
            var myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
            Encoding qwe = Encoding.UTF8;
            try
            {
                qwe = Encoding.GetEncoding(myHttpWebResponse.CharacterSet);
            }
            catch
            {
            }
            string result = new StreamReader(myHttpWebResponse.GetResponseStream(), qwe).ReadToEnd().Replace("\n", "").Replace("\r", "");
            myHttpWebResponse.Close();
            //есть ответ, надо его пропарсить..
            Match m = _rGetPost.Match(result);
            return m.Success ? m.Groups[1].ToString() : "";
        }


        /// <summary>
        /// Возвращает список комментов на запись переданную в bp...
        /// Но только те, что новее переданной даты!!
        /// </summary>
        /// <param name="bp">ссылка на пост, без извращений</param>
        /// <returns></returns>
        /// <remarks>https://blogs.yandex.ru/search.rss?ft=comments&full=1&post=http%3A%2F%2Fdolboeb.livejournal.com%2F1602948.html</remarks>
        public YandexParsed ExtractCommentsNew(String bp)
        {
            var oRet = new YandexParsed();
            try
            {
                HttpWebRequest myHttpWebRequest = MakeRequest(FormYandexComments(bp));
                myHttpWebRequest.Method = "GET"; // метод GET
                myHttpWebRequest.Referer = "https://blogs.yandex.ru";
                //получаем ответ и его разбираем...
                var myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
                Encoding useenc = Encoding.GetEncoding(1251);
                try
                {
                    useenc = Encoding.GetEncoding(myHttpWebResponse.CharacterSet);
                }
                catch { }
                string result = new StreamReader(myHttpWebResponse.GetResponseStream(), useenc).ReadToEnd();
                myHttpWebResponse.Close();
                //ПОЛУЧИЛИ xml - откроемка его...
                oRet.Parse(result);
            }
            catch (Exception e1)
            {
                Debug.WriteLine("Ошибка загрузки комментариев: " + e1.Message);
            }
            return oRet;
        }

        /// <summary>
        /// Возвращает список записей ссылающихся на запись переданную в bp...
        /// Но только те, что новее переданной даты!!
        /// </summary>
        /// <param name="bp">ссылка на пост, без извращений</param>
        /// <returns></returns>
        /// <remarks>https://blogs.yandex.ru/search.rss?link=http%3A%2F%2Fdrugoi.livejournal.com%2F3031817.html&full=1</remarks>
        public YandexParsed ExtractLinksNew(String bp)
        {
            var oRet = new YandexParsed();
            try
            {
                HttpWebRequest myHttpWebRequest = MakeRequest(FormYandexLinks(bp));
                myHttpWebRequest.Method = "GET"; // метод GET
                myHttpWebRequest.Referer = "https://blogs.yandex.ru";
                //получаем ответ и его разбираем...
                var myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
                Encoding useenc = Encoding.GetEncoding(1251);
                try
                {
                    useenc = Encoding.GetEncoding(myHttpWebResponse.CharacterSet);
                }
                catch { }
                string result = new StreamReader(myHttpWebResponse.GetResponseStream(), useenc).ReadToEnd();
                myHttpWebResponse.Close();
                //ПОЛУЧИЛИ xml - откроемка его...
                oRet.Parse(result);
            }
            catch (Exception e1)
            {
                Debug.WriteLine("Ошибка загрузки ссылок: " + e1.Message);
            }
            return oRet;
        }


        /// <summary>
        /// Возвращает параметры пользователя из яндекса ...
        /// </summary>
        /// <param name="bloglink">ссылка на blog</param>
        /// <returns></returns>
        //public Match ExtractCounts(String bloglink)
        //{

        //    Match oRet = null;
        //    String userName;
        //    BlogType bt;
        //    BlogServer bs =
        //        (BlogServer)Common.GetBlogServiceByLink(bloglink, out userName, out bt);
        //    try
        //    {
        //        HttpWebRequest myHttpWebRequest = MakeRequest(FormYandexReaders(bs.GetBlogLink(userName, bt), bt));
        //        myHttpWebRequest.Method = "GET"; // метод GET
        //        myHttpWebRequest.Referer = "http://blogs.yandex.ru";
        //        //получаем ответ и его разбираем...
        //        HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
        //        Encoding useenc = Encoding.GetEncoding(1251);
        //        try
        //        {
        //            useenc = Encoding.GetEncoding(myHttpWebResponse.CharacterSet);
        //        }
        //        catch { }
        //        string result = new StreamReader(myHttpWebResponse.GetResponseStream(), useenc).ReadToEnd();
        //        myHttpWebResponse.Close();
        //        //ПОЛУЧИЛИ xml - откроемка его...
        //        oRet = _rCountReaders.Match(result);
        //    }
        //    catch (Exception e1)
        //    {
        //        Debug.WriteLine("Ошибка загрузки данных о блоге: " + e1.Message);
        //    }
        //    return oRet;
        //}

        /// <summary>
        /// Получение списка популярных запросов
        /// </summary>
        /// <param name="onlyrus">только на РУССКОМ ЯЗЫКЕ!!</param>
        /// <param name="from">День в который смотрим популярные запрсоы</param>
        /// <returns></returns>
        //public List<String> GetTopRequests(bool onlyrus, DateTime? from)
        //{
        //    var oRet = new List<string>(0);
        //    Regex rRequests;
        //    if (onlyrus)
        //    {
        //        rRequests =
        //        new Regex(@"<a\s+href\W+[^>]+?cat=request[^>]+>([а-я ]+)</a",
        //                  RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Compiled);
        //    }
        //    else
        //    {
        //        rRequests =
        //        new Regex(@"<a\s+href\W+[^>]+?cat=request[^>]+>([^>]+)</a",
        //                  RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Compiled);
        //    }
        //    try
        //    {
        //        HttpWebRequest myHttpWebRequest =
        //            MakeRequest(String.Format("https://blogs.yandex.ru/rating/requests/?date={0}",
        //            from.HasValue ? from.Value.ToString("yyyy-MM-dd") : ""));
        //        myHttpWebRequest.Method = "GET"; // метод GET
        //        myHttpWebRequest.Referer = "https://blogs.yandex.ru";
        //        //получаем ответ и его разбираем...
        //        HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
        //        Encoding useenc = Encoding.GetEncoding(1251);
        //        try
        //        {
        //            useenc = Encoding.GetEncoding(myHttpWebResponse.CharacterSet);
        //        }
        //        catch { }
        //        string result = new StreamReader(myHttpWebResponse.GetResponseStream(), useenc).ReadToEnd();
        //        myHttpWebResponse.Close();
        //        //ПОЛУЧИЛИ xml - откроемка его...
        //        MatchCollection mc = rRequests.Matches(result);
        //        if (mc.Count > 0)
        //        {
        //            oRet.AddRange(from Match match in mc select match.Groups[1].Value);
        //        }
        //    }
        //    catch (Exception e1)
        //    {
        //        Debug.WriteLine("Ошибка извлечения списка популярных запросов: " + e1.Message);
        //    }
        //    return oRet;
        //}
    }
}
